#ifndef MAP_H
#define MAP_H

#include "MapPoint.h"
#include "KeyFrame.h"

#include <set>
#include <mutex>

namespace ORB_SLAM2
{

class MapPoint;
class KeyFrame;

class Map
{
public:

    Map();


    // 向地图中添加关键帧
    void AddKeyFrame(KeyFrame* pKF);

    // 向地图中添加地图点
    void AddMapPoint(MapPoint* pMP);

    // 从地图中擦除地图点
    void EraseMapPoint(MapPoint* pMP);

    /**
     * @brief 从地图中删除关键帧
     * @details 实际上这个函数中目前仅仅是删除了在std::set中保存的地图点的指针,并且删除后
     * 之前的地图点所占用的内存其实并没有得到释放
     * @param[in] pKF 关键帧
     */
    void EraseKeyFrame(KeyFrame* pKF);

    /**
     * @brief 设置参考地图点
     * @details 一般是指,设置当前帧中的参考地图点; 这些点将用于DrawMapPoints函数画图
     * 
     * @param[in] vpMPs 地图点们
     */
    void SetReferenceMapPoints(const std::vector<MapPoint*> &vpMPs);

    void InformNewBigChange();

    // 获取最大改变
    int GetLastBigChangeIdx();

    // 获取地图中的所有关键帧
    std::vector<KeyFrame*> GetAllKeyFrames();

    // 获取地图中的所有地图点
    std::vector<MapPoint*> GetAllMapPoints();

    // 获取地图中的所有参考地图点
    std::vector<MapPoint*> GetReferenceMapPoints();

    // 获得当前地图中的地图点个数
    long unsigned int MapPointsInMap();

    // 获取当前地图中的关键帧个数
    long unsigned  KeyFramesInMap();

    // 获取关键帧的最大id
    long unsigned int GetMaxKFid();

    // 清空地图
    void clear();

    // 保存了最初始的关键帧
    vector<KeyFrame*> mvpKeyFrameOrigins;

    // 当更新地图时的互斥量.回环检测中和局部BA后更新全局地图的时候会用到这个
    std::mutex mMutexMapUpdate;

    // This avoid that two points are created simultaneously in separate threads (id conflict)
    // 为了避免地图点id冲突设计的互斥量
    std::mutex mMutexPointCreation;

protected:
    // 存储所有的地图点
    std::set<MapPoint*> mspMapPoints; 

    // 存储所有的关键帧（只存关键帧）
    std::set<KeyFrame*> mspKeyFrames; 

    // 参考地图点
    std::vector<MapPoint*> mvpReferenceMapPoints;

    // 当前地图中具有最大ID的关键帧
    long unsigned int mnMaxKFid;

    // Index related to a big change in the map (loop closure, global BA)
    int mnBigChangeIdx;

    // 类的成员函数在对类成员变量进行操作的时候,防止冲突的互斥量
    std::mutex mMutexMap;
};

} //namespace ORB_SLAM

#endif // MAP_H
